﻿using Abp.UI;
using Aop.Api;
using Aop.Api.Domain;
using Aop.Api.Request;
using Aop.Api.Response;
using Aop.Api.Util;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Configuration;

namespace Pay.AliPay
{
    /// <summary>
    /// 支付宝支付
    /// </summary>
    public class AliPayContext
    {
        private const string server = "https://openapi.alipay.com/gateway.do";
        private const string alipaypublickey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlMsM3MjLJUtQZis2dJ1uodasWon9CR66p5lgFLWxnScFpXl9tLGgIpfbOx81kc0XdnTvAEz3/aWz4pnwHypBEuXvL1DqQ0tCYrR4fsE/izC6TM87RFjvTS3FJihMBtmyK6f60kdLB2LrRARLxOIH0cNus2TxFZXfjIOfzm5TAZU5JBFOQG3qhMU1cLJ6Qc+YydAyKVa6N1HXurXxt9fByXKnjM/pJUO/roEnugbsgzRSgPYgR793knbi5GGLEAd/wRYn3ou5zk5MjqAPY1pov+wLweRSzxalf37xFUeQhPcPB1a8+xi+AGSElB0sKPzxLZmxr+oTpiMSIyogbuxUdwIDAQAB";
        private const string signType = "RSA2";
        private const string charset = "utf-8";
        /// <summary>
        /// 支付宝分配给开发者的应用id
        /// </summary>
        public string appid { get; set; }
        /// <summary>
        /// 合作者账号
        /// </summary>
        public string sellerid { get; set; }
        /// <summary>
        /// 回调地址
        /// </summary>
        public string notifyurl { get; set; }
        /// <summary>
        /// RSA私钥
        /// </summary>
        private string privatekey { get; set; }
        /// <summary>
        /// 付款账户名（个人支付宝账号是真实姓名公司支付宝账号是公司名称）
        /// </summary>
        private string account { get; set; }

        private static AliPayContext instance = null;
        public static AliPayContext Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new AliPayContext();
                }
                return instance;
            }
        }
        public AliPayContext()
        {
            appid = WebConfigurationManager.AppSettings["alipay_appid"];
            sellerid = WebConfigurationManager.AppSettings["alipay_sellerid"];
            notifyurl = WebConfigurationManager.AppSettings["alipay_notifyurl"];
            privatekey = WebConfigurationManager.AppSettings["alipay_privatekey"];
        }
        /// <summary>
        /// 下单参数
        /// </summary>
        /// <param name="tradeNo">外部单号</param>
        /// <param name="subject">主题</param>
        /// <param name="body">内容</param>
        /// <param name="totalfee">总金额</param>
        /// <param name="attach">附加参数</param>
        /// <returns></returns>
        public string PreOrder(string tradeNo, string subject, string body, string totalfee)
        {
            IAopClient client = new DefaultAopClient(server, appid, privatekey, "json", "1.0", signType, alipaypublickey, charset, false);
            //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称如：alipay.trade.app.pay
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            model.Body = body;
            model.Subject = subject;
            model.TotalAmount = totalfee;
            model.ProductCode = "QUICK_MSECURITY_PAY";
            model.OutTradeNo = tradeNo;
            model.TimeoutExpress = "30m";
            request.SetBizModel(model);
            request.SetNotifyUrl(notifyurl);
            //这里和普通的接口调用不同，使用的是sdkExecute
            AlipayTradeAppPayResponse response = client.SdkExecute(request);
            //HttpUtility.HtmlEncode是为了输出到页面时防止被浏览器将关键参数html转义，实际打印到日志以及http传输不会有这个问题
            //Response.Write(HttpUtility.HtmlEncode(response.Body));
            //页面输出的response.Body就是orderString 可以直接给客户端请求，无需再做处理。
            return response.Body;
        }


        public string RefundOrder(string outTradeNo, string outRequestNo, string refundfee)
        {
            //实例化客户端
            IAopClient client = new DefaultAopClient(server, appid, privatekey, "json", "1.0", signType, alipaypublickey, charset, false);
            AlipayTradeRefundModel refundModel = new AlipayTradeRefundModel();
            refundModel.OutTradeNo = outTradeNo;
            refundModel.RefundAmount = refundfee;
            refundModel.OutRequestNo = outRequestNo;
            refundModel.RefundReason = "商品退款";
            //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            request.SetBizModel(refundModel);
            try
            {
                AlipayTradeRefundResponse response = client.Execute(request);
                return response.Msg;
            }
            catch (Exception e)
            {
                return e.Message;
            }
        }


        public RefunStatus RefundQuery(string outRequestNo,string outTradeNo)
        {
            //实例化客户端
            IAopClient client = new DefaultAopClient(server, appid, privatekey, "json", "1.0", signType, alipaypublickey, charset, false);
            AlipayTradeFastpayRefundQueryModel refundModel = new AlipayTradeFastpayRefundQueryModel();
            refundModel.OutRequestNo = outRequestNo;
            refundModel.OutTradeNo = outTradeNo;
            AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
            request.SetBizModel(refundModel);
            try
            {
                AlipayTradeFastpayRefundQueryResponse response = client.Execute(request);
                Writelog("支付宝返回状态" + response.SubCode + response.SubMsg);
                if (response.Msg == "Success")
                    return RefunStatus.SUCCESS;
                else
                    return RefunStatus.PROCESSING;
            }
            catch (Exception e)
            {
                throw new UserFriendlyException(e.Message);
            }
        }

        public static void Writelog(string msg)
        {
            StreamWriter stream;
            //写入日志内容
            string path = AppDomain.CurrentDomain.BaseDirectory;
            //检查上传的物理路径是否存在，不存在则创建
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            stream = new StreamWriter(path + "\\log.txt", true, Encoding.Default);
            stream.Write(DateTime.Now.ToString() + ":" + msg);
            stream.Write("\r\n");
            stream.Flush();
            stream.Close();
        }

        public bool Verify(SortedDictionary<string, string> sParam)
        {
            return AlipaySignature.RSACheckV1(sParam, alipaypublickey, charset, signType, false);
        }
    }
}
